﻿using KingsSharp.Common;
using KingsSharp.Common.Extensions;
using KingsSharp.Common.Filter;
using KingsSharp.Core.Data.Entity;
using KingsSharp.Core.Data.Extensions;
using KingsSharp.Web.Helper;
using KingsSharp.Web.Mvc.Binders;
using KingsSharp.Web.Mvc.Security;
using KingsSharp.Web.UI;
using CRM.Admin.Contracts.Contract.Sys;
using CRM.Admin.Contracts.Dto.Sys;
using CRM.Admin.Contracts.Model.Sys;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;

namespace CRM.Admin.Areas.Sys.Controllers
{
    public class DictionaryController : Controller
    {
        /// <summary>
        /// excle导入字典时提供的数据表模版名称
        /// </summary>
        private const string DICTIONARYDATA = "字典数据";
        /// <summary>
        /// excle导入时作为参考的字典类别
        /// </summary>
        private const string DICTIONARYDATATYPE = "字典类别参考";
        /// <summary> 
        /// 数据字典操作契约
        /// </summary>
        private IDictionaryService _dictionaryservice;

        public DictionaryController(IDictionaryService dictionaryservice)
        {
            _dictionaryservice = dictionaryservice;
        }

        #region 视图功能

        public ActionResult DictionaryCheck(string TypeCode, bool Multi = false)
        {
            ViewBag.TypeCode = TypeCode;
            ViewBag.Multi = Multi.ToLower();
            var zTree = GetDictionaryTypeZtreeData(TypeCode);
            return View((object)zTree.ToJsonString(true));
        }

        public ActionResult DictionaryIndex()
        {
            var zTree = GetDictionaryTypeZtreeData();
            return View((object)zTree.ToJsonString(true));
        }
        /// <summary>
        /// 字典-新增
        /// </summary>
        /// <returns></returns>
        public ActionResult DictionaryAdd()
        {
            return View();
        }
        /// <summary>
        /// 字典-编辑
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ActionResult DictionaryEdit(Guid Id)
        {
            return View(_dictionaryservice.ItemDictionary
                .Where(entity => entity.Id == Id).FirstOrDefault().MapTo<DictionaryDto>());
        }
        /// <summary>
        /// 字典类别-新增
        /// </summary>
        /// <returns></returns>
        public ActionResult DictionaryTypeAdd()
        {
            return View();
        }
        /// <summary>
        /// 字典类别-编辑
        /// </summary>
        /// <param name="CatalogId"></param>
        /// <returns></returns>
        public ActionResult DictionaryTypeEdit(Guid CatalogId)
        {
            return View(_dictionaryservice.ItemDictionaryType.
                Where(entity => entity.Id == CatalogId).FirstOrDefault().MapTo<DictionaryTypeDto>());
        }
        /// <summary>
        /// 数据导入
        /// </summary>
        /// <returns></returns>
        public ActionResult DictionaryImport()
        {
            return View();
        }
        /// <summary>
        /// 字典-模版导出
        /// </summary>
        /// <returns></returns>
        public ActionResult DictionaryTemplate()
        {
            //创建excle并写标题
            var book = ExcleHelper.Create(DICTIONARYDATA, "字典名称", "字典描述", "排序号", "上级目录");

            //创建一行数据  如示例数据
            book.AppendData(DICTIONARYDATA, "中秋祝福", "中秋节发送给大家的祝福短信", 1, "祝福信息");

            //创建另一个sheet，当填写数据需要参考数据时，如存在父子关系的数据，用户不知道上级的编码
            book.CreateSheet(DICTIONARYDATATYPE, "类别名称", "类别编码", "类别说明");

            var typedata = _dictionaryservice.ItemDictionaryType
                .Where(entity => entity.IsDeleted == false).ToList().MapToList<DictionaryType, DictionaryTypeDto>();

            //写参考数据
            book.AppendListData(DICTIONARYDATATYPE, typedata, (dto, cell, i) =>
            {
                switch (i)
                {
                    case 0:
                        cell.SetCellValue(dto.Name);
                        break;
                    case 1:
                        cell.SetCellValue(dto.Code);
                        break;
                    case 2:
                        cell.SetCellValue(dto.Description);
                        break;
                }
            });
            return File(book.ToStream(true), "application/vnd.ms-excel", "数据字典导入模版.xls");//导出excle
        }
        /// <summary>
        /// 字典类别树
        /// </summary>
        /// <returns></returns>
        public ActionResult DictionaryTypeTree()
        {
            var zTree = GetDictionaryTypeZtreeData();
            return View((object)zTree.ToJsonString(true));
        }
        #endregion

        #region 数据功能
        /// <summary>
        /// 字典数据新增
        /// </summary>
        /// <param name="dtos">字典dto</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DictionaryAdd([ModelBinder(typeof(JsonBinder<DictionaryDto>))] DictionaryDto dtos)
        {
            dtos.CheckNotNull("dtos");
            dtos.Id = Guid.NewGuid();
            var result = _dictionaryservice.AddDictionary(dtos);
            string msg = result.Message ?? result.ResultType.ToDescription();
            AjaxResultType msgType = result.ResultType.ToAjaxResultType();
            if (msgType != AjaxResultType.Error)
            {
                msg = "字典“{0}”添加成功。".FormatWith(dtos.Name);//这就是返回的json数据中的值。
            }
            return Json(new AjaxResult(msg, msgType));
        }
        /// <summary>
        /// 字典数据修改
        /// </summary>
        /// <param name="dtos">字典dto</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DictionaryEdit([ModelBinder(typeof(JsonBinder<DictionaryDto>))] DictionaryDto dtos)
        {
            dtos.CheckNotNull("dtos");
            var result = _dictionaryservice.EditDictionary(dtos);
            string msg = result.Message ?? result.ResultType.ToDescription();
            AjaxResultType msgType = result.ResultType.ToAjaxResultType();
            if (msgType != AjaxResultType.Error)
            {
                msg = "字典“{0}”修改成功。".FormatWith(dtos.Name);
            }
            return Json(new AjaxResult(msg, msgType));
        }
        /// <summary>
        /// 字典类别保存
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DictionaryTypeAdd([ModelBinder(typeof(JsonBinder<DictionaryTypeDto>))] DictionaryTypeDto dtos)
        {
            dtos.CheckNotNull("dtos");
            dtos.Id = Guid.NewGuid();
            var result = _dictionaryservice.AddDictionaryType(dtos);
            string msg = result.Message ?? result.ResultType.ToDescription();
            AjaxResultType msgType = result.ResultType.ToAjaxResultType();
            if (msgType != AjaxResultType.Error)
            {
                msg = "字典类别“{0}”添加成功。".FormatWith(dtos.Name);
            }
            return Json(new AjaxResult(msg, msgType));
        }
        /// <summary>
        /// 字典类别修改
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DictionaryTypeEdit([ModelBinder(typeof(JsonBinder<DictionaryTypeDto>))] DictionaryTypeDto dtos)
        {
            dtos.CheckNotNull("dtos");
            var result = _dictionaryservice.EditDictionaryType(dtos);
            string msg = result.Message ?? result.ResultType.ToDescription();
            AjaxResultType msgType = result.ResultType.ToAjaxResultType();
            if (msgType != AjaxResultType.Error)
            {
                msg = "字典类别“{0}”修改成功。".FormatWith(dtos.Name);
            }
            return Json(new AjaxResult(msg, msgType));
        }
        [HttpPost]
        public ActionResult DeleteDictionary(string deleteids)
        {
            string[] delids = deleteids.Split(',');
            List<Guid> ids = new List<Guid>();
            for (int i = 0; i < delids.Length; i++)
            {
                ids.Add(new Guid(delids[i]));
            }
            ids.CheckNotNull("ids");
            var result = _dictionaryservice.DeleteDictionary(ids.ToArray());
            string msg = result.Message ?? result.ResultType.ToDescription();
            AjaxResultType msgType = result.ResultType.ToAjaxResultType();

            return Json(new AjaxResult(msg, msgType));
        }
        /// <summary>
        /// 分页获取字典列表数据
        /// </summary>
        /// <returns></returns>
        public ActionResult GetDictionaryGridData()
        {
            GridRequest request = new GridRequest(Request);
            Expression<Func<Dictionary, bool>> predicate = FilterHelper.GetExpression<Dictionary>(request.FilterGroup);
            int total;
            var data = _dictionaryservice.ItemDictionary.
                Where<Dictionary, Guid>(predicate, request.PageCondition, out total).
                Where(a => a.IsDeleted == false).
                Select(dto => new
                {
                    dto.Id,
                    dto.Name,
                    dto.IsDeleted,
                    dto.Order,
                    dto.Description,
                    DictionaryTypeName = dto.Parent.Name,
                }).ToList();
            return Json(new GridData<object>(data, total), JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 获取菜单类别数据
        /// </summary>
        /// <returns></returns>
        [AjaxOnly]
        public ActionResult GetDictionaryTypeTree()
        {
            var zTree = GetDictionaryTypeZtreeData();
            return Json(zTree.ToJsonString(true), JsonRequestBehavior.AllowGet);
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 获取全部字典类别数据并转为ztree树形数据
        /// </summary>
        /// <returns></returns>
        private ICollection<ZTreeNode> GetDictionaryTypeZtreeData()
        {
            var data = _dictionaryservice.ItemDictionaryType.Where(entity => entity.IsDeleted == false)
                .OrderByDescending(entity => entity.Order).ToList();

            var zTree = data.RenderTree<DictionaryType, ZTreeNode>(data.Where(node =>
                node.Parent == null).ToList(), (catalog, level) =>
                {
                    return new ZTreeNode()
                    {
                        Id = catalog.Id.ToString(),
                        Name = catalog.Name,
                        Order = catalog.Order,
                        Open = level < 3,
                        obj = catalog.Parent != null ? catalog.Parent.Id.ToString() : ""
                    };
                }, (catalog, sources) =>
                {
                    var templist = sources.Where(a => a.Parent != null
                        && a.Parent.Id == catalog.Id).ToList();
                    return templist;
                }, (parentNode, newNode,Items) =>
                {
                    if (newNode.obj.ToString() != "" && Items.Any(a => a.Id == newNode.obj.ToString()))
                    {
                        parentNode = Items.FirstOrDefault(a => a.Id == newNode.obj.ToString());
                    }
                    if (parentNode.Children == null)
                    {
                        parentNode.Children = new List<ZTreeNode>();
                    }
                    parentNode.Children.Add(newNode);
                });
            return zTree;
        }

        private ICollection<ZTreeNode> GetDictionaryTypeZtreeData(string TypeCode)
        {
            var data = _dictionaryservice.ItemDictionaryType.Where(entity => entity.IsDeleted == false)
                .OrderByDescending(entity => entity.Order).ToList();

            var zTree = data.RenderTree<DictionaryType, ZTreeNode>(data.Where(node =>
                node.Parent == null && node.Code == TypeCode).ToList(), (catalog, level) =>
                {
                    return new ZTreeNode()
                    {
                        Id = catalog.Id.ToString(),
                        Name = catalog.Name,
                        Order = catalog.Order,
                        Open = level < 3,
                        obj = catalog.Parent != null ? catalog.Parent.Id.ToString() : ""
                    };
                }, (catalog, sources) =>
                {
                    return sources.Where(a => a.Parent != null
                        && a.Parent.Id == catalog.Id).ToList();
                }, (parentNode, newNode,Items) =>
                {
                    if (newNode.obj!=null && newNode.obj.ToString() != "" && Items.Any(a => a.Id == newNode.obj.ToString()))
                    {
                        parentNode = Items.FirstOrDefault(a => a.Id == newNode.obj.ToString());
                    }
                    if (parentNode.Children == null)
                    {
                        parentNode.Children = new List<ZTreeNode>();
                    }
                    parentNode.Children.Add(newNode);
                });
            return zTree;
        }
        #endregion
    }
}